
package uk.ac.cam.cl.oscar;

import uk.ac.cam.cl.oscar.edgefinder.*;
import uk.ac.cam.cl.oscar.sift.*;


import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.*;
import javax.media.jai.*;
import java.util.*;
import java.lang.*;

class MagicImage extends Component 
{
	public BufferedImage inputImage; 
	private String imageFileName;	
	private BufferedImage outputImage;

	public MagicImage (String imageFileName) {
		this.imageFileName = imageFileName;
		outputImage = null;
	}

	public void init() {
            try {
                inputImage = ImageOperations.load (imageFileName);
            }
            catch (Exception e) {
                System.out.println ("Failed to load " + imageFileName);
                e.printStackTrace();
            }
        }
        
        //load a new image file
	public void load (File file) {
		inputImage = ImageOperations.load (file);
		outputImage = null;
		paint(getGraphics());
	}
        
        // highlight high-gradient edges
	public void findEdges () {
		outputImage = EdgeFinder.findEdges (inputImage);
		paint(getGraphics());
	}

	public void kernelConv () {
		int mw = 2; int mh = 2;
		float[] mtx = new float[mw*mh];
		mtx[0] = -1;
		mtx[1] = 0;
		mtx[2] = 1;
		mtx[3] = 0;
	
		outputImage = ImageOperations.convolve2D (inputImage, mtx, mw, mh);
		
		paint (getGraphics());
	}
	
        // apply Gaussian blur
	public void blur () {
		outputImage = ImageOperations.gaussian2D (inputImage, 40, 2.0);
		paint(getGraphics());
	}
	
        //scale the image by given factor
	public void scale (float f) {
		outputImage = ImageOperations.scale (inputImage, f);
		paint(getGraphics());
	}
	
        
	public void sifty () {
            //find keypoints
            Vector<Keypoint> kplist = SIFT.findKeypoints(inputImage);

            //copy the input image to output
            outputImage = ImageOperations.scale (inputImage, 1.0);

            
            for (int i=0; i<kplist.size(); i++) {
               Keypoint kp = kplist.elementAt(i);

               int x = (int)Math.round(kp.getX());
               int y = (int)Math.round(kp.getY());
               
               //mark all keypoints with red dots on the output image
	       outputImage.setRGB (x, y, 0xFF0000 + (int)Math.round(50 * (kp.getScale()-0.5)) );
               
               //add a second blue dot next to each red one for visibility
               if (x+1 < outputImage.getWidth()){
         	  outputImage.setRGB (x+1, y, 0x0000FF);
               }
           
            }
            paint (getGraphics());
	}
	
	public void search () {
		System.out.println ("Commencing search...");
		Vector<ImageRecord> matches = ImageFinder.getMatches (inputImage);
		System.out.println ("Returned " + matches.size() + " matches");
		if (matches.size() > 0) {
			outputImage = matches.get(0).getThumbnail();
			paint (getGraphics());
		}
		for (ImageRecord ir : matches) {
			if (ir != null)
				System.out.println ("Poster " + ir.getPosterId() + " score: " + ir.getScore());
		}
	}
	
	public void createDB () {
		DBAdaptor.createTables();
		System.out.println ("Created Tables");
	}
	
	public void dropDB () {
		DBAdaptor.dropTables();
		System.out.println ("Drop Tables");
	}
	
	public void populateDB () {
		DBAdaptor.populate("tests/");
		System.out.println ("Populated Tables");
	}
	
	public void extractRectangle () {
		outputImage = EdgeFinder.extractRectangle (inputImage);
		paint (getGraphics());
	}
	
	public void getRandom () {
		Random r = new Random();
		int i = 1 + Math.abs(r.nextInt())%13;
		outputImage = DBAdaptor.getImage (i);
		paint (getGraphics());
	}
	
	public void reset () {
		outputImage = null;
		paint (getGraphics());
	}

	public void paint(Graphics g) {
		g.clearRect(0, 0, 1000, 1000);
    	g.drawImage(outputImage!=null?outputImage:inputImage, 0, 0, null);
    }

}

public class SimpleImageTests extends JApplet{
	
    MagicImage image;
    JComboBox combi;
    JMenu menu;
    JMenuBar menubar;
    JMenuItem menuload;
 
    public void buildUI() {
        add("Center", image);
        JButton magicButton = new JButton("Magic");
        magicButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    String action = (String)combi.getSelectedItem();
                    
                    if (action == "Kernel Convolve") image.kernelConv();
                    else if (action == "Gaussian Blur") image.blur();
                    else if (action == "Find Rectangle") image.extractRectangle();
                    else if (action == "Find Keypoints") image.sifty();
                    else if (action == "Zoom in") image.scale(2.0f);
                    else if (action == "Shrink") image.scale(0.5f);
                    else if (action == "DB Match") image.search();
                    else if (action == "DB Create") image.createDB();
                    else if (action == "DB Search") image.search();
                    else if (action == "DB Drop") image.dropDB();
                    else if (action == "DB Populate") image.populateDB();
                    else if (action == "Get Random Image") image.getRandom();
                    else if (action == "Find Edges") image.findEdges();
                    else image.reset();
                    
                    
                };
            });
            
        String[] actionStrings = {"DB Search", "Find Keypoints", "DB Populate", "Find Edges", "Gaussian Blur", "Find Rectangle", "Zoom in", "Shrink", "DB Match", "DB Create", "DB Drop", "Get Random Image", "Reset" };
        combi = new JComboBox(actionStrings);
        
        Box box = Box.createHorizontalBox();
        box.add("South", combi);
        box.add("South East", magicButton); 
        add ("South", box);
        
        menubar = new JMenuBar();
        menu = new JMenu ("Image");
        menubar.add(menu);
        menuload = new JMenuItem("Load");
        final SimpleImageTests outer = this;
        menuload.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                	JFileChooser fc = new JFileChooser("");
                	int returnVal = fc.showOpenDialog(outer);

					if (returnVal == JFileChooser.APPROVE_OPTION) {
						File file = fc.getSelectedFile();
						outer.load (file);
					}
                };
            });
            
        menu.add (menuload);
        add(menubar, "North");
        
    }

    public void load (File file) {
            image.load (file);
    }

    public static void main(String s[]) {
    	
        //disable native accelerator
        System.setProperty("com.sun.media.jai.disableMediaLib", "true");
        
        JFrame f = new JFrame("Image");
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        
        SimpleImageTests app = new SimpleImageTests ();
        app.image = new MagicImage ( s.length == 0 ? "../kitten.jpg" : s[0] );
    	app.image.init();
	    	
        app.buildUI ();
        f.add("Center", app);
        f.pack();
        f.setSize(600, 550);
        f.setVisible(true);
    }
}
